package generator;

import baza.BazaDanych;
import java.util.*;
import klient.Klient;
import uslugi.*;
import util.KategoriaEnum;

enum RodzajKlienta {
	INWESTOR, KREDYTOBIORCA
};

enum Istotnosc {
	NISKA, WYSOKA
};

enum Zaangazowanie {
	NISKIE, WYSOKIE
};

public class Kategoryzacja {

	private BazaDanych bd;

	private Vector<Klient> klienci;

	// mapa zaangazowanie klienta
	// Integer[0] - ilosc kont
	// Integer[1] - ilosc lokat
	// Integer[2]] - ilosc kredytow
	private Map<Klient, Integer[]> mapaAngazu = new HashMap<Klient, Integer[]>();

	private Vector<Konto> konta;
	private Vector<LokataKlienta> lokaty;
	private Vector<KredytKlienta> kredyty;

	public Kategoryzacja() {

		podlaczDoBazy();

		for (Klient k : klienci) {
			przypiszKategorie(k);
		}
	}

	public Vector<Klient> getKlienci() {
		return klienci;
	}

	private void podlaczDoBazy() {

		bd = new BazaDanych();

		klienci = bd.stworzListe("klient");
		bd.stworzListe("lokata");
		bd.stworzListe("kredyt");
		konta = bd.stworzListe("konto");
		lokaty = bd.stworzListe("lokataKlienta");
		kredyty = bd.stworzListe("kredytKlienta");

		ladujKonta();
		ladujKredyty();
		ladujLokaty();

	}

	private void przypiszKategorie(Klient klient) {

		RodzajKlienta typKlienta;
		Istotnosc istotnoscKlienta;
		Zaangazowanie zaangazowanieKlienta;

		typKlienta = okreslRodzajKlienta(klient);

		istotnoscKlienta = okreslIstotnoscKlienta(klient);

		zaangazowanieKlienta = okreslZaangazowanieKlienta(klient);

		KategoriaEnum kat = okreslKategorie(typKlienta, istotnoscKlienta,
				zaangazowanieKlienta);
		
		klient.setKategoria(kat);

	}

	private KategoriaEnum okreslKategorie(RodzajKlienta rk, Istotnosc i,
			Zaangazowanie z) {

		switch (i) {
		case NISKA:
			switch (z) {
			case NISKIE:
				return KategoriaEnum.F;
			case WYSOKIE:
				return KategoriaEnum.E;
			}
		case WYSOKA:
			switch (rk) {
			case INWESTOR:
				switch (z) {
				case NISKIE:
					return KategoriaEnum.B;
				case WYSOKIE:
					return KategoriaEnum.A;
				}
			case KREDYTOBIORCA:
				switch (z) {
				case NISKIE:
					return KategoriaEnum.D;
				case WYSOKIE:
					return KategoriaEnum.C;
				}
			}
		}

	throw new RuntimeException("Niemoznosc przypisania klienta do kategorii!!");
	
	}

	private RodzajKlienta okreslRodzajKlienta(Klient k) {

		// wspOszczednosci, im wyzszy tym klientem bardziej zainteresowany
		// inwestowaniem, np. w lokaty, im nizszy tym wiekszy popyt na kredyt
		int wspOszczednosci = 0;

		// najwazniejszy punkt wspOszczednosci, stosunek oszczednosci do dochodu
		wspOszczednosci = (int) (((double) k.getOszczednosciMsc() / k
				.getDochod()) * 100);

		switch (k.getStanCywilny()) {
		case S:
			wspOszczednosci += 5;
		case M:
			wspOszczednosci -= 5;
		}

		switch (k.getMieszkanie()) {
		case WYN:
			wspOszczednosci -= 5;
		case WLAS:
			wspOszczednosci += 5;
		}

		if (wspOszczednosci > 50) {
			return RodzajKlienta.INWESTOR;

		} else {
			return RodzajKlienta.KREDYTOBIORCA;
		}

	}

	private Istotnosc okreslIstotnoscKlienta(Klient k) {

		int punktyIstotnosci = 0;

		punktyIstotnosci += k.getDochod() / 1000;
		switch (k.getWyksztalcenie()) {
		case P:
			punktyIstotnosci += 5;
			break; // podstawowe
		case Z:
			punktyIstotnosci += 7;
			break; // zawodowe
		case S:
			punktyIstotnosci += 8;
			break; // srednie
		case W:
			punktyIstotnosci += 11;
			break; // wyzsze
		}

		if (punktyIstotnosci < 15) {
			return Istotnosc.NISKA;
		} else {
			return Istotnosc.WYSOKA;
		}

	}

	private Zaangazowanie okreslZaangazowanieKlienta(Klient k) {

		int punktyZaangazowania = 0;

		if (!mapaAngazu.containsKey(k)) {
		} else {

			Integer[] punktyTab = mapaAngazu.get(k);

			// ilosc kont
			punktyZaangazowania += punktyTab[0] * 25;

			// ilosc lokat
			punktyZaangazowania += punktyTab[1] * 15;

			// ilosc kredytow
			punktyZaangazowania += punktyTab[2] * 15;
		}

		if (punktyZaangazowania < 40) {
			return Zaangazowanie.NISKIE;
		} else {
			return Zaangazowanie.WYSOKIE;
		}

	}

	private void ladujKonta() {

		for (Konto konto : konta) {

			Klient wlasciciel = konto.getWlasciciel();

			if (mapaAngazu.containsKey(wlasciciel)) {
				Integer[] ilosc = mapaAngazu.get(wlasciciel);
				ilosc[0] += 1;
				mapaAngazu.put(wlasciciel, ilosc);
			} else {
				mapaAngazu.put(wlasciciel, new Integer[] { 1, 0, 0 });
			}

		}

	}

	private void ladujLokaty() {

		for (LokataKlienta lk : lokaty) {

			Klient wlasciciel = lk.getWlasciciel();

			if (mapaAngazu.containsKey(wlasciciel)) {
				Integer[] ilosc = mapaAngazu.get(wlasciciel);
				ilosc[1] += 1;
				mapaAngazu.put(wlasciciel, ilosc);
			} else {
				mapaAngazu.put(wlasciciel, new Integer[] { 0, 1, 0 });
			}

		}

	}

	private void ladujKredyty() {

		for (KredytKlienta kk : kredyty) {

			Klient wlasciciel = kk.getKlient();

			if (mapaAngazu.containsKey(wlasciciel)) {
				Integer[] ilosc = mapaAngazu.get(wlasciciel);
				ilosc[2] += 1;
				mapaAngazu.put(wlasciciel, ilosc);
			} else {
				mapaAngazu.put(wlasciciel, new Integer[] { 0, 0, 1 });
			}

		}

	}

	public static void main(String[] args) {

		Kategoryzacja k = new Kategoryzacja();

		for(Klient klient: k.getKlienci()){
			System.out.println(klient);
		}
		
	}

}
